home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 19 / Mac Magazin and MacEasy Magazine CD - Issue 19.iso / Utilities / uae-0.4 / Source Code / custom.c < prev    next >
Text File  |  1996-02-13  |  61KB  |  2,219 lines

  1.  /* 
  2.   * UAE - The Un*x Amiga Emulator
  3.   * 
  4.   * Custom chip emulation
  5.   * 
  6.   * (c) 1995 Bernd Schmidt, Alessandro Bissacco
  7.   */
  8.  
  9. #include <ctype.h>
  10. #ifdef __unix
  11. #include <sys/time.h>
  12. #include <unistd.h>
  13. #endif
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <stdlib.h>
  17. #include <assert.h>
  18.  
  19. #include "config.h"
  20. #include "amiga.h"
  21. #include "options.h"
  22. #include "events.h"
  23. #include "memory.h"
  24. #include "custom.h"
  25. #include "cia.h"
  26. #include "disk.h"
  27. #include "blit.h"
  28. #include "xwin.h"
  29. #include "os.h"
  30.  
  31. #define DMA_AUD0      0x0001
  32. #define DMA_AUD1      0x0002
  33. #define DMA_AUD2      0x0004
  34. #define DMA_AUD3      0x0008
  35. #define DMA_DISK      0x0010
  36. #define DMA_SPRITE    0x0020
  37. #define DMA_BLITTER   0x0040
  38. #define DMA_COPPER    0x0080
  39. #define DMA_BITPLANE  0x0100
  40. #define DMA_BLITPRI   0x0400
  41.  
  42. /* These are default values for mouse emulation.
  43.  * The first two are default values for mstepx and mstepy.
  44.  * The second line set the orizontal and vertical offset for amiga and X 
  45.  * pointer matching
  46.  */
  47.    
  48. #define defstepx (1<<16)
  49. #define defstepy (1<<16)
  50. #ifndef __mac__
  51. #define defxoffs 0
  52. #define defyoffs 0
  53. #else
  54. #define defxoffs 210
  55. #define defyoffs 85
  56. #endif
  57.  
  58. /* Values below define mouse auto calibration process.
  59.  * They are not critical, change them if you want.
  60.  * The most important is calweight, which sets mouse adjustement rate */ 
  61.  
  62. static const int docal = 60, xcaloff = 40, ycaloff = 20;
  63. static const int calweight = 3;
  64.  
  65. static int lastsampledmx, lastsampledmy;
  66.  
  67.  /*
  68.   * Events
  69.   */
  70.  
  71. unsigned long int cycles, nextevent, nextev_count, specialflags;
  72. int vpos;
  73. UWORD lof;
  74.  
  75. struct ev eventtab[ev_max];
  76.  
  77. bool copper_active;
  78.  
  79. static const int maxhpos = 227,maxvpos = 312;
  80. static const int dskdelay = 2; /* FIXME: ??? */
  81. static const int minfirstline = 29;
  82.  
  83.  /* 
  84.   * hardware register values that are visible/can be written to by someone
  85.   */
  86.  
  87. static UWORD cregs[256];
  88.  
  89. static UWORD dmacon,intena,intreq,adkcon;
  90.  
  91. static ULONG cop1lc,cop2lc,copcon;
  92.  
  93. static CPTR  bpl1pt,bpl2pt,bpl3pt,bpl4pt,bpl5pt,bpl6pt;
  94. static ULONG bpl1dat,bpl2dat,bpl3dat,bpl4dat,bpl5dat,bpl6dat;
  95. static UWORD bplcon0,bplcon1,bplcon2,bplcon3;
  96. static UWORD diwstrt,diwstop,ddfstrt,ddfstop;
  97. static WORD  bpl1mod,bpl2mod;
  98.  
  99. static UWORD sprdata[8], sprdatb[8], sprctl[8], sprpos[8];
  100. static ULONG sprpt[8];
  101. static bool sprarmed[8], sprptset[8];
  102. /* Kludge. FIXME: How does sprite restart after vsync work? */
  103. static int spron[8]; 
  104.  
  105. static UWORD bltadat,bltbdat,bltcdat,bltddat,bltafwm,bltalwm,bltsize;
  106. static WORD  bltamod,bltbmod,bltcmod,bltdmod;
  107. static UWORD bltcon0,bltcon1;
  108. static ULONG bltapt,bltbpt,bltcpt,bltdpt,bltcnxlpt,bltdnxlpt;
  109.  
  110. static ULONG dskpt;
  111. static UWORD dsklen,dsksync;
  112.  
  113. static int joy0x, joy1x, joy0y, joy1y;
  114. static int lastspr0x,lastspr0y,lastdiffx,lastdiffy,spr0pos,spr0ctl;
  115. static int mstepx,mstepy,xoffs=defxoffs,yoffs=defyoffs;
  116. static int sprvbfl;
  117.  
  118. static enum { normal_mouse, dont_care_mouse, follow_mouse} mousestate;
  119.  
  120. xcolnr acolors[64];
  121. UWORD color_regs[32];
  122.  
  123.  /*
  124.   * "hidden" hardware registers
  125.   */
  126.  
  127. static int dblpf_ind1[64], dblpf_ind2[64];
  128.  
  129. static ULONG coplc;
  130. static UWORD copi1,copi2;
  131.  
  132. static enum {
  133.     COP_stop, COP_read, COP_wait, COP_move, COP_skip
  134. } copstate;
  135.  
  136. static UWORD vblitsize,hblitsize,blitpreva,blitprevb;
  137. static UWORD blitlpos,blitashift,blitbshift,blinea,blineb;
  138. static bool blitline,blitfc,blitzero,blitfill,blitife,blitdesc,blitsing;
  139. static bool blitonedot,blitsign;
  140. static long int bltwait;
  141.  
  142. static int dsklength;
  143.  
  144. static enum {
  145.     BLT_done, BLT_init, BLT_read, BLT_work, BLT_write, BLT_next
  146. } bltstate;
  147.  
  148. static int plffirstline,plflastline,plfstrt,plfstop,plflinelen;
  149. static int diwfirstword,diwlastword;
  150. static int plf1pri, plf2pri;
  151.  
  152. int dskdmaen; /* used in cia.c */
  153. static UWORD dskmfm,dskbyte,dsktime;
  154. static bool dsksynced;
  155.  
  156. static int bpldelay1;
  157. static int bpldelay2;
  158. static bool bplhires;
  159. static int bplplanecnt;
  160.  
  161. static bool pfield_fullline,pfield_linedone;
  162. static bool pfield_linedmaon;
  163. static int pfield_lastpart_hpos;
  164.  
  165. unsigned char apixels[1000]; /* includes a lot of safety padding */
  166. char spixels[1000]; /* for sprites */
  167. char spixstate[1000]; /* more sprites */
  168.  
  169.  /*
  170.   * Statistics
  171.   */
  172.  
  173. static unsigned long int msecs = 0, frametime = 0, timeframes = 0;
  174. static unsigned long int seconds_base;
  175. bool bogusframe;
  176.  
  177.  /*
  178.   * helper functions
  179.   */
  180.  
  181. static void pfield_doline_slow(int);
  182. static void pfield_doline(void);
  183. static void pfield_hsync(int);
  184.  
  185. bool inhibit_frame;
  186. static int framecnt = 0;
  187.  
  188. static __inline__ void count_frame(void)
  189. {
  190.     if (inhibit_frame) 
  191.         framecnt = 1;
  192.     else {    
  193.     framecnt++;
  194.     if (framecnt == framerate)
  195.             framecnt = 0;
  196.     }
  197. }
  198.  
  199. static __inline__ void setclr(UWORD *p, UWORD val)
  200. {
  201.     if (val & 0x8000) {
  202.     *p |= val & 0x7FFF;
  203.     } else {
  204.     *p &= ~val;
  205.     }
  206. }
  207.  
  208. bool dmaen(UWORD dmamask)
  209. {
  210.     return (dmamask & dmacon) && (dmacon & 0x200);
  211. }
  212.  
  213. static __inline__ int current_hpos(void)
  214. {
  215.     return cycles - eventtab[ev_hsync].oldcycles;
  216. }
  217.  
  218. static void calcdiw(void)
  219. {
  220.     diwfirstword = (diwstrt & 0xFF) * 2 - 0x60;
  221.     diwlastword  = (diwstop & 0xFF) * 2 + 0x200 - 0x60;
  222.     if (diwfirstword < 0) diwfirstword = 0;
  223.  
  224.     plffirstline = diwstrt >> 8;
  225.     plflastline = diwstop >> 8;
  226. #if 0
  227.     /* This happens far too often. */
  228.     if (plffirstline < minfirstline) {
  229.     fprintf(stderr, "Warning: Playfield begins before line %d!\n", minfirstline);
  230.     plffirstline = minfirstline;
  231.     }
  232. #endif
  233.     if ((plflastline & 0x80) == 0) plflastline |= 0x100;
  234. #if 0 /* Turrican does this */
  235.     if (plflastline > 313) {
  236.     fprintf(stderr, "Warning: Playfield out of range!\n");
  237.     plflastline = 313;
  238.     }
  239. #endif
  240.     plfstrt = ddfstrt;
  241.     plfstop = ddfstop;
  242.     if (plfstrt < 0x18) plfstrt = 0x18;
  243.     if (plfstop > 0xD8) plfstop = 0xD8;
  244.     if (plfstrt > plfstop) plfstrt = plfstop;
  245.     
  246.     /* 
  247.      * Prize question: What are the next lines supposed to be?
  248.      * I can't seem to get it right.
  249.      */
  250. #if 0
  251.     /* Pretty good guess, but wrong. */
  252.     plflinelen = (plfstop-plfstrt+15) & ~7;
  253.     plfstrt &= ~(bplhires ? 3 : 7);
  254.     plfstop &= ~(bplhires ? 3 : 7);
  255. #endif
  256.     plfstrt &= ~(bplhires ? 3 : 3);
  257.     plfstop &= ~(bplhires ? 3 : 3);
  258.     plflinelen = (plfstop-plfstrt+15) & ~7;
  259. }
  260.  
  261. static void pfield_may_need_update(bool colreg)
  262. {
  263.     int i;
  264.     
  265.     /* Ignore, if this happened before or after the DDF window */
  266.     if (framecnt != 0 || !pfield_linedmaon || current_hpos() <= plfstrt
  267.     || vpos < plffirstline || vpos >= plflastline)
  268.     {    
  269.         return;
  270.     }
  271.     /* 
  272.      * If a color reg was modified, it is only important if we are within
  273.      * the DIW.
  274.      */
  275.     if (current_hpos() <= (diwfirstword+0x60)/4 && colreg)
  276.         return;
  277.  
  278.     /*
  279.      * If we are past the DDF window, me might as well draw the complete
  280.      * line now.
  281.      */
  282.     if (current_hpos() > plfstrt + plflinelen && pfield_fullline) {
  283.     if (!pfield_linedone)
  284.         pfield_doline();
  285.     pfield_linedone = true;
  286.     return;
  287.     }
  288.         
  289.     if (pfield_fullline) {
  290.     pfield_lastpart_hpos = 0;
  291.     memset(apixels, 0, sizeof(apixels));
  292.     pfield_fullline = false;
  293.     } else {    
  294.     assert(pfield_lastpart_hpos <= current_hpos());
  295.     }
  296.     for (i = pfield_lastpart_hpos; i < current_hpos(); i++) {
  297.     pfield_doline_slow(i);
  298.     }
  299.     pfield_lastpart_hpos = current_hpos();
  300. }
  301.  
  302. /* Apparently, the DMA bit is tested by the hardware at some point,
  303.  * presumably at the ddfstart position, to determine whether it
  304.  * ought to draw the line.
  305.  * This is probably not completely correct, but should not matter
  306.  * very much.
  307.  */
  308. static void pfield_calclinedma(void)
  309. {
  310.     if (current_hpos() >= plfstrt)
  311.         return;
  312.     
  313.     pfield_linedmaon = dmaen(DMA_BITPLANE);
  314. }
  315.  
  316.  /* 
  317.   * register functions
  318.   */
  319.  
  320. static UWORD DMACONR(void)
  321. {
  322.     return (dmacon | (bltstate==BLT_done ? 0 : 0x4000)
  323.         | (blitzero ? 0x2000 : 0));
  324. }
  325. static UWORD INTENAR(void) { return intena; }
  326. static UWORD INTREQR(void) { return intreq; }
  327. static UWORD ADKCONR(void) { return adkcon; }
  328. static UWORD VPOSR(void) { return (vpos >> 8) | lof; }
  329. static void  VPOSW(UWORD v)  { lof = v & 0x8000; }
  330. static UWORD VHPOSR(void) { return (vpos << 8) | current_hpos(); } 
  331.  
  332. static void  COP1LCH(UWORD v) { cop1lc= (cop1lc & 0xffff) | ((ULONG)v << 16); }
  333. static void  COP1LCL(UWORD v) { cop1lc= (cop1lc & ~0xffff) | v; }
  334. static void  COP2LCH(UWORD v) { cop2lc= (cop2lc & 0xffff) | ((ULONG)v << 16); }
  335. static void  COP2LCL(UWORD v) { cop2lc= (cop2lc & ~0xffff) | v; }
  336.  
  337. static void  COPJMP1(UWORD a)
  338. {
  339.     coplc = cop1lc; copstate = COP_read; 
  340.     eventtab[ev_copper].active = 1; eventtab[ev_copper].oldcycles = cycles;
  341.     eventtab[ev_copper].evtime = 4; events_schedule();
  342.     copper_active = true;
  343. }
  344. static void  COPJMP2(UWORD a)
  345. {
  346.     coplc = cop2lc; copstate = COP_read; 
  347.     eventtab[ev_copper].active = 1; eventtab[ev_copper].oldcycles = cycles;
  348.     eventtab[ev_copper].evtime = 4; events_schedule();
  349.     copper_active = true;
  350. }
  351.  
  352. static void  DMACON(UWORD v) 
  353. {
  354.     UWORD oldcon = dmacon;
  355.     setclr(&dmacon,v); dmacon &= 0x1FFF;
  356.     pfield_calclinedma();
  357.     
  358.     if ((dmacon & DMA_COPPER) > (oldcon & DMA_COPPER)) { 
  359.     COPJMP1(0); /* @@@ not sure how this works */
  360.     }
  361.     if (copper_active && !eventtab[ev_copper].active) {
  362.     eventtab[ev_copper].active = true;
  363.     eventtab[ev_copper].oldcycles = cycles;
  364.     eventtab[ev_copper].evtime = 1;
  365.     events_schedule();
  366.     }
  367. }
  368. static void  INTENA(UWORD v) { setclr(&intena,v); specialflags |= SPCFLAG_INT; }
  369. static void  INTREQ(UWORD v) { setclr(&intreq,v); specialflags |= SPCFLAG_INT; }
  370. static void  ADKCON(UWORD v) { setclr(&adkcon,v); }
  371.  
  372. static void  BPL1PTH(UWORD v) { bpl1pt= (bpl1pt & 0xffff) | ((ULONG)v << 16); }
  373. static void  BPL1PTL(UWORD v) { bpl1pt= (bpl1pt & ~0xffff) | v; }
  374. static void  BPL2PTH(UWORD v) { bpl2pt= (bpl2pt & 0xffff) | ((ULONG)v << 16); }
  375. static void  BPL2PTL(UWORD v) { bpl2pt= (bpl2pt & ~0xffff) | v; }
  376. static void  BPL3PTH(UWORD v) { bpl3pt= (bpl3pt & 0xffff) | ((ULONG)v << 16); }
  377. static void  BPL3PTL(UWORD v) { bpl3pt= (bpl3pt & ~0xffff) | v; }
  378. static void  BPL4PTH(UWORD v) { bpl4pt= (bpl4pt & 0xffff) | ((ULONG)v << 16); }
  379. static void  BPL4PTL(UWORD v) { bpl4pt= (bpl4pt & ~0xffff) | v; }
  380. static void  BPL5PTH(UWORD v) { bpl5pt= (bpl5pt & 0xffff) | ((ULONG)v << 16); }
  381. static void  BPL5PTL(UWORD v) { bpl5pt= (bpl5pt & ~0xffff) | v; }
  382. static void  BPL6PTH(UWORD v) { bpl6pt= (bpl6pt & 0xffff) | ((ULONG)v << 16); }
  383. static void  BPL6PTL(UWORD v) { bpl6pt= (bpl6pt & ~0xffff) | v; }
  384.  
  385. /*
  386.  * I've seen the listing of an example program that changes 
  387.  * from lo- to hires while a line is being drawn. That's
  388.  * awful, but we want to emulate it.
  389.  */
  390. static void  BPLCON0(UWORD v) 
  391. {
  392.     pfield_may_need_update(false);
  393.     bplcon0 = v;
  394.     bplhires = (bplcon0 & 0x8000) == 0x8000; 
  395.     bplplanecnt = (bplcon0 & 0x7000) >> 12; 
  396.     calcdiw(); /* This should go away. */
  397. }
  398. static void  BPLCON1(UWORD v) 
  399. {
  400.     pfield_may_need_update(false);
  401.     bplcon1 = v; 
  402.     bpldelay1 = bplcon1 & 0xF; 
  403.     bpldelay2 = (bplcon1 >> 4) & 0xF; 
  404. }
  405. static void  BPLCON2(UWORD v) 
  406. {
  407.     pfield_may_need_update(false); 
  408.     bplcon2 = v;
  409.     plf1pri = 1 << 2*(v & 7);
  410.     plf2pri = 1 << 2*((v>>3) & 7);
  411. }
  412. static void  BPLCON3(UWORD v) { pfield_may_need_update(false); bplcon3 = v; }
  413.  
  414. static void  BPL1MOD(UWORD v) { pfield_may_need_update(false); bpl1mod = v; }
  415. static void  BPL2MOD(UWORD v) { pfield_may_need_update(false); bpl2mod = v; }
  416.  
  417. static void  BPL1DAT(UWORD v) { bpl1dat = v; }
  418. static void  BPL2DAT(UWORD v) { bpl2dat = v; }
  419. static void  BPL3DAT(UWORD v) { bpl3dat = v; }
  420. static void  BPL4DAT(UWORD v) { bpl4dat = v; }
  421. static void  BPL5DAT(UWORD v) { bpl5dat = v; }
  422. static void  BPL6DAT(UWORD v) { bpl6dat = v; }
  423.  
  424. /* We call pfield_may_need_update() from here. Actually, 
  425.  * I have no idea what happens if someone changes ddf or
  426.  * diw mid-line, and I don't really want to know. I doubt
  427.  * that this sort of thing was ever used to create a
  428.  * useful effect.
  429.  */
  430. static void  DIWSTRT(UWORD v) { pfield_may_need_update(false); diwstrt = v; calcdiw(); }
  431. static void  DIWSTOP(UWORD v) { pfield_may_need_update(false); diwstop = v; calcdiw(); }
  432. static void  DDFSTRT(UWORD v) { pfield_may_need_update(false); ddfstrt = v; calcdiw(); }
  433. static void  DDFSTOP(UWORD v) { pfield_may_need_update(false); ddfstop = v; calcdiw(); }
  434.  
  435. static void  BLTADAT(UWORD v) { bltadat = v; }
  436. static void  BLTBDAT(UWORD v) { bltbdat = v; }
  437. static void  BLTCDAT(UWORD v) { bltcdat = v; }
  438.  
  439. static void  BLTAMOD(UWORD v) { bltamod = v; }
  440. static void  BLTBMOD(UWORD v) { bltbmod = v; }
  441. static void  BLTCMOD(UWORD v) { bltcmod = v; }
  442. static void  BLTDMOD(UWORD v) { bltdmod = v; }
  443.  
  444. static void  BLTCON0(UWORD v) { bltcon0 = v; }
  445. static void  BLTCON1(UWORD v) { bltcon1 = v; }
  446.  
  447. static void  BLTAFWM(UWORD v) { bltafwm = v; }
  448. static void  BLTALWM(UWORD v) { bltalwm = v; }
  449.  
  450. static void  BLTAPTH(UWORD v) { bltapt= (bltapt & 0xffff) | ((ULONG)v << 16); }
  451. static void  BLTAPTL(UWORD v) { bltapt= (bltapt & ~0xffff) | (v); }
  452. static void  BLTBPTH(UWORD v) { bltbpt= (bltbpt & 0xffff) | ((ULONG)v << 16); }
  453. static void  BLTBPTL(UWORD v) { bltbpt= (bltbpt & ~0xffff) | (v); }
  454. static void  BLTCPTH(UWORD v) { bltcpt= (bltcpt & 0xffff) | ((ULONG)v << 16); }
  455. static void  BLTCPTL(UWORD v) { bltcpt= (bltcpt & ~0xffff) | (v); }
  456. static void  BLTDPTH(UWORD v) { bltdpt= (bltdpt & 0xffff) | ((ULONG)v << 16); }
  457. static void  BLTDPTL(UWORD v) { bltdpt= (bltdpt & ~0xffff) | (v); }
  458. static void  BLTSIZE(UWORD v) { bltsize = v; bltstate = BLT_init; specialflags |= SPCFLAG_BLIT; }
  459.  
  460. static void  SPRxCTL(UWORD v, int num) { pfield_may_need_update(false); sprctl[num] = v; sprarmed[num] = false; spron[num] |= 2; }
  461. static void  SPRxPOS(UWORD v, int num) { pfield_may_need_update(false); sprpos[num] = v; }
  462. static void  SPRxDATA(UWORD v, int num) { pfield_may_need_update(false); sprdata[num] = v; sprarmed[num] = true; }
  463. static void  SPRxDATB(UWORD v, int num) { pfield_may_need_update(false); sprdatb[num] = v; }
  464. static void  SPRxPTH(UWORD v, int num) { sprpt[num] &= 0xffff; sprpt[num] |= (ULONG)v << 16; spron[num] |= 1; }
  465. static void  SPRxPTL(UWORD v, int num) { sprpt[num] &= ~0xffff; sprpt[num] |= v; spron[num] |= 1; }
  466.  
  467. static void  COLOR(UWORD v, int num)
  468. {
  469.     pfield_may_need_update(true);
  470.     color_regs[num] = v;
  471.     acolors[num] = xcolors[v];
  472.     acolors[num+32] = xcolors[(v >> 1) & 0x777];
  473. }
  474.  
  475. static void  DSKSYNC(UWORD v) { dsksync = v; }
  476. static void  DSKDAT(UWORD v) { dskmfm = v; }
  477. static void  DSKPTH(UWORD v) { dskpt = (dskpt & 0xffff) | ((ULONG)v << 16); }
  478. static void  DSKPTL(UWORD v) { dskpt = (dskpt & ~0xffff) | (v); }
  479.  
  480. static void  DSKLEN(UWORD v) 
  481. {
  482.     if (v & 0x8000) { dskdmaen++; } else { dskdmaen = 0; }
  483.     dsktime = dskdelay; dsksynced = false;
  484.     dsklen = dsklength = v; dsklength &= 0x3fff;
  485.     if (dskdmaen == 2 && dsksync != 0x4489 && (adkcon & 0x400)) {
  486.     printf("Non-standard sync: %04x len: %x\n", dsksync, dsklength);
  487.     }
  488.     if (dsklen & 0x4000) DISK_InitWrite();
  489.     if (dskdmaen) specialflags |= SPCFLAG_DISK;
  490. }
  491.  
  492. static UWORD DSKBYTR(void)
  493. {
  494.     UWORD v = (dsklen >> 1) & 0x6000;
  495.     v |= dskbyte;
  496.     dskbyte &= ~0x8000;
  497.     if (dsksync == dskmfm) v |= 0x1000;
  498.     return v;
  499. }
  500.  
  501. static UWORD DSKDATR(void) { return dskmfm; }
  502. static UWORD POTGOR(void)
  503. {
  504.     if (!buttonstate[2]) {    
  505.     return 0xffff;
  506.     } else {
  507.     return 0xbbff;
  508.     }
  509. }
  510.  
  511. static UWORD JOY0DAT(void) { return joy0x + (joy0y << 8); }
  512. static UWORD JOY1DAT(void)
  513. {
  514. #ifdef HAVE_JOYSTICK
  515.     UWORD dir;
  516.     bool button;
  517.     read_joystick(&dir, &button);
  518.     buttonstate[1] = button;
  519.     return dir;
  520. #else
  521.     return joy1x + (joy1y << 8);
  522. #endif
  523. }
  524. static void JOYTEST(UWORD v)
  525. {
  526.     joy0x = joy1x = v & 0xFC;
  527.     joy0y = joy1y = (v >> 8) & 0xFC;    
  528. }
  529. static void AUD0LCH(UWORD v) { audlc[0] = (audlc[0] & 0xffff) | ((ULONG)v << 16); }
  530. static void AUD0LCL(UWORD v) { audlc[0] = (audlc[0] & ~0xffff) | v; }
  531. static void AUD1LCH(UWORD v) { audlc[1] = (audlc[1] & 0xffff) | ((ULONG)v << 16); }
  532. static void AUD1LCL(UWORD v) { audlc[1] = (audlc[1] & ~0xffff) | v; }
  533. static void AUD2LCH(UWORD v) { audlc[2] = (audlc[2] & 0xffff) | ((ULONG)v << 16); }
  534. static void AUD2LCL(UWORD v) { audlc[2] = (audlc[2] & ~0xffff) | v; }
  535. static void AUD3LCH(UWORD v) { audlc[3] = (audlc[3] & 0xffff) | ((ULONG)v << 16); }
  536. static void AUD3LCL(UWORD v) { audlc[3] = (audlc[3] & ~0xffff) | v; }
  537. static void AUD0PER(UWORD v) { audper[0] = v; }
  538. static void AUD1PER(UWORD v) { audper[1] = v; }
  539. static void AUD2PER(UWORD v) { audper[2] = v; }
  540. static void AUD3PER(UWORD v) { audper[3] = v; }
  541. static void AUD0VOL(UWORD v) { audvol[0] = v; }
  542. static void AUD1VOL(UWORD v) { audvol[1] = v; }
  543. static void AUD2VOL(UWORD v) { audvol[2] = v; }
  544. static void AUD3VOL(UWORD v) { audvol[3] = v; }
  545. static void AUD0LEN(UWORD v) { audlen[0] = v; }
  546. static void AUD1LEN(UWORD v) { audlen[1] = v; }
  547. static void AUD2LEN(UWORD v) { audlen[2] = v; }
  548. static void AUD3LEN(UWORD v) { audlen[3] = v; }
  549.  
  550. /* Custom chip memory bank */
  551.  
  552. static ULONG custom_lget(CPTR) REGPARAM;
  553. static UWORD custom_wget(CPTR) REGPARAM;
  554. static UBYTE custom_bget(CPTR) REGPARAM;
  555. static void  custom_lput(CPTR, ULONG) REGPARAM;
  556. static void  custom_wput(CPTR, UWORD) REGPARAM;
  557. static void  custom_bput(CPTR, UBYTE) REGPARAM;
  558.  
  559. addrbank custom_bank = {
  560.     custom_lget, custom_wget, custom_bget,
  561.     custom_lput, custom_wput, custom_bput,
  562.     default_xlate, default_check
  563. };
  564.  
  565. UWORD custom_wget(CPTR addr)
  566. {
  567. #ifdef DUALCPU
  568.     customacc = true;
  569. #endif
  570.     switch(addr & 0x1FE) {
  571.      case 0x002: return DMACONR();
  572.      case 0x004: return VPOSR();
  573.      case 0x006: return VHPOSR();
  574.     
  575.      case 0x008: return DSKDATR();
  576.      case 0x016: return POTGOR();
  577.      case 0x01A: return DSKBYTR();
  578.      case 0x01C: return INTENAR();
  579.      case 0x01E: return INTREQR();
  580.      case 0x010: return ADKCONR();
  581.      case 0x00A: return JOY0DAT();
  582.      case 0x00C: return JOY1DAT();
  583.      default:
  584.     custom_wput(addr,0);
  585.     return 0xffff;
  586.     }
  587. }
  588.  
  589. UBYTE custom_bget(CPTR addr)
  590. {
  591.     return custom_wget(addr & 0xfffe) >> (addr & 1 ? 0 : 8);
  592. }
  593.  
  594. ULONG custom_lget(CPTR addr)
  595. {
  596.     return ((ULONG)custom_wget(addr & 0xfffe) << 16) | custom_wget((addr+2) & 0xfffe);
  597. }
  598.  
  599. void custom_wput(CPTR addr, UWORD value)
  600. {
  601. #ifdef DUALCPU
  602.     customacc = true;
  603. #endif
  604.     addr &= 0x1FE;
  605.     cregs[addr>>1] = value;
  606.     switch(addr) {    
  607.      case 0x020: DSKPTH(value); break;
  608.      case 0x022: DSKPTL(value); break;
  609.      case 0x024: DSKLEN(value); break;
  610.      case 0x026: DSKDAT(value); break;
  611.     
  612.      case 0x02A: VPOSW(value); break;
  613.     
  614.      case 0x040: BLTCON0(value); break;
  615.      case 0x042: BLTCON1(value); break;
  616.     
  617.      case 0x044: BLTAFWM(value); break;
  618.      case 0x046: BLTALWM(value); break;
  619.     
  620.      case 0x050: BLTAPTH(value); break;
  621.      case 0x052: BLTAPTL(value); break;
  622.      case 0x04C: BLTBPTH(value); break;
  623.      case 0x04E: BLTBPTL(value); break;
  624.      case 0x048: BLTCPTH(value); break;
  625.      case 0x04A: BLTCPTL(value); break;
  626.      case 0x054: BLTDPTH(value); break;
  627.      case 0x056: BLTDPTL(value); break;
  628.     
  629.      case 0x058: BLTSIZE(value); break;
  630.     
  631.      case 0x064: BLTAMOD(value); break;
  632.      case 0x062: BLTBMOD(value); break;
  633.      case 0x060: BLTCMOD(value); break;
  634.      case 0x066: BLTDMOD(value); break;
  635.     
  636.      case 0x070: BLTCDAT(value); break;
  637.      case 0x072: BLTBDAT(value); break;
  638.      case 0x074: BLTADAT(value); break;
  639.             
  640.      case 0x07E: DSKSYNC(value); break;
  641.  
  642.      case 0x080: COP1LCH(value); break;
  643.      case 0x082: COP1LCL(value); break;
  644.      case 0x084: COP2LCH(value); break;
  645.      case 0x086: COP2LCL(value); break;
  646.     
  647.      case 0x088: COPJMP1(value); break;
  648.      case 0x08A: COPJMP2(value); break;
  649.     
  650.      case 0x08E: DIWSTRT(value); break;
  651.      case 0x090: DIWSTOP(value); break;
  652.      case 0x092: DDFSTRT(value); break;
  653.      case 0x094: DDFSTOP(value); break;
  654.     
  655.      case 0x096: DMACON(value); break;
  656.      case 0x09A: INTENA(value); break;
  657.      case 0x09C: INTREQ(value); break;
  658.      case 0x09E: ADKCON(value); break;
  659.     
  660.      case 0x0A0: AUD0LCH(value); break;
  661.      case 0x0A2: AUD0LCL(value); break;
  662.      case 0x0A4: AUD0LEN(value); break;
  663.      case 0x0A6: AUD0PER(value); break;
  664.      case 0x0A8: AUD0VOL(value); break;
  665.     
  666.      case 0x0B0: AUD1LCH(value); break;
  667.      case 0x0B2: AUD1LCL(value); break;
  668.      case 0x0B4: AUD1LEN(value); break;
  669.      case 0x0B6: AUD1PER(value); break;
  670.      case 0x0B8: AUD1VOL(value); break;
  671.     
  672.      case 0x0C0: AUD2LCH(value); break;
  673.      case 0x0C2: AUD2LCL(value); break;
  674.      case 0x0C4: AUD2LEN(value); break;
  675.      case 0x0C6: AUD2PER(value); break;
  676.      case 0x0C8: AUD2VOL(value); break;
  677.     
  678.      case 0x0D0: AUD3LCH(value); break;
  679.      case 0x0D2: AUD3LCL(value); break;
  680.      case 0x0D4: AUD3LEN(value); break;
  681.      case 0x0D6: AUD3PER(value); break;
  682.      case 0x0D8: AUD3VOL(value); break;
  683.     
  684.      case 0x0E0: BPL1PTH(value); break;
  685.      case 0x0E2: BPL1PTL(value); break;
  686.      case 0x0E4: BPL2PTH(value); break;
  687.      case 0x0E6: BPL2PTL(value); break;
  688.      case 0x0E8: BPL3PTH(value); break;
  689.      case 0x0EA: BPL3PTL(value); break;
  690.      case 0x0EC: BPL4PTH(value); break;
  691.      case 0x0EE: BPL4PTL(value); break;
  692.      case 0x0F0: BPL5PTH(value); break;
  693.      case 0x0F2: BPL5PTL(value); break;
  694.      case 0x0F4: BPL6PTH(value); break;
  695.      case 0x0F6: BPL6PTL(value); break;
  696.     
  697.      case 0x100: BPLCON0(value); break;
  698.      case 0x102: BPLCON1(value); break;
  699.      case 0x104: BPLCON2(value); break;
  700.      case 0x106: BPLCON3(value); break;
  701.     
  702.      case 0x108: BPL1MOD(value); break;
  703.      case 0x10A: BPL2MOD(value); break;
  704.  
  705.      case 0x110: BPL1DAT(value); break;
  706.      case 0x112: BPL2DAT(value); break;
  707.      case 0x114: BPL3DAT(value); break;
  708.      case 0x116: BPL4DAT(value); break;
  709.      case 0x118: BPL5DAT(value); break;
  710.      case 0x11A: BPL6DAT(value); break;
  711.     
  712.      case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A:
  713.      case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196:
  714.      case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2:
  715.      case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE:
  716.      case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA:
  717.      case 0x1BC: case 0x1BE: 
  718.     COLOR(value & 0xFFF, (addr & 0x3E) / 2);
  719.     break;    
  720.      case 0x120: case 0x124: case 0x128: case 0x12C: 
  721.      case 0x130: case 0x134: case 0x138: case 0x13C:
  722.     SPRxPTH(value, (addr - 0x120) / 4);
  723.     break;
  724.      case 0x122: case 0x126: case 0x12A: case 0x12E: 
  725.      case 0x132: case 0x136: case 0x13A: case 0x13E:
  726.     SPRxPTL(value, (addr - 0x122) / 4);
  727.     break;
  728.      case 0x140: case 0x148: case 0x150: case 0x158: 
  729.      case 0x160: case 0x168: case 0x170: case 0x178:
  730.     SPRxPOS(value, (addr - 0x140) / 8);
  731.     break;
  732.      case 0x142: case 0x14A: case 0x152: case 0x15A: 
  733.      case 0x162: case 0x16A: case 0x172: case 0x17A:
  734.     SPRxCTL(value, (addr - 0x142) / 8);
  735.     break;
  736.      case 0x144: case 0x14C: case 0x154: case 0x15C:
  737.      case 0x164: case 0x16C: case 0x174: case 0x17C:
  738.     SPRxDATA(value, (addr - 0x144) / 8);
  739.     break;
  740.      case 0x146: case 0x14E: case 0x156: case 0x15E: 
  741.      case 0x166: case 0x16E: case 0x176: case 0x17E:
  742.     SPRxDATB(value, (addr - 0x146) / 8);
  743.     break;
  744.     
  745.      case 0x36: JOYTEST(value); break;    
  746.     }
  747. }
  748.  
  749. void custom_bput(CPTR addr, UBYTE value)
  750. {
  751.     /* Yes, there are programs that do this. The programmers should be shot.
  752.      * This might actually work sometimes. */
  753.     UWORD rval = value;
  754.     CPTR raddr = addr & 0x1FE;
  755.     if (addr & 1) {
  756.     rval |= cregs[raddr >> 1] & 0xFF00;
  757.     } else {
  758.     rval <<= 8;
  759.     rval |= cregs[raddr >> 1] & 0xFF;
  760.     }
  761.     custom_wput(raddr, rval);
  762. }
  763.  
  764. void custom_lput(CPTR addr, ULONG value)
  765. {
  766.     custom_wput(addr & 0xfffe, value >> 16);
  767.     custom_wput((addr+2) & 0xfffe, (UWORD)value);
  768. }
  769.  
  770. static bool copcomp(void)
  771. {
  772.     UWORD vp = vpos & (((copi2 >> 8) & 0x7F) | 0x80);
  773.     UWORD hp = current_hpos() & (copi2 & 0xFE);
  774.     UWORD vcmp = copi1 >> 8;
  775.     UWORD hcmp = copi1 & 0xFE;
  776.     return (vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000));
  777. }
  778.  
  779. /*
  780.  * Calculate the minimum number of cycles after which the
  781.  * copper comparison becomes true. This is quite tricky. I hope it works.
  782.  */
  783. static int calc_copcomp_true(int currvpos, int currhpos)
  784. {    
  785.     UWORD vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
  786.     UWORD hp = currhpos & (copi2 & 0xFE);
  787.     UWORD vcmp = copi1 >> 8;
  788.     UWORD hcmp = copi1 & 0xFE;
  789.  
  790.     int cycleadd = maxhpos - currhpos;
  791.     int coptime = 0;
  792.  
  793.     if ((vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000)))
  794.         return 0;    
  795.     
  796.     try_again:
  797.     
  798.     while (vp < vcmp) {
  799.     currvpos++;
  800.     if (currvpos > maxvpos + 1)
  801.         return -1;
  802.     currhpos = 0;
  803.     coptime += cycleadd;
  804.     cycleadd = maxhpos;
  805.     vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
  806.     }
  807.     hp = currhpos & (copi2 & 0xFE);
  808.     if (!(vp > vcmp)) {    
  809.     while (hp < hcmp) {
  810.         currhpos++;
  811.         if (currhpos > maxhpos) {
  812.         /* Now, what? There might be a good position on the
  813.          * next line. But it can also be the FFFF FFFE
  814.          * case.
  815.          */
  816.         currhpos = 0;
  817.         currvpos++;
  818.         vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
  819.         goto try_again;
  820.         }
  821.         coptime++;
  822.         hp = currhpos & (copi2 & 0xFE);
  823.     }
  824.     }
  825.     if (coptime == 0) /* waiting for the blitter */
  826.         return 1;
  827.     
  828.     return coptime;
  829. }
  830.  
  831. static void copper_read(void)
  832. {
  833.     if (dmaen(DMA_COPPER)){
  834.     copi1 = chipmem_bank.wget(coplc); 
  835.     copi2 = chipmem_bank.wget(coplc+2);
  836.     coplc += 4;
  837.     eventtab[ev_copper].oldcycles = cycles;
  838.     eventtab[ev_copper].evtime = (copi1 & 1) ? (copi2 & 1) ? 4 : 6 : 4;
  839.     copstate = (copi1 & 1) ? (copi2 & 1) ? COP_skip : COP_wait : COP_move;
  840.     } else {
  841.     copstate = COP_read;
  842.     eventtab[ev_copper].active = false;
  843.     }
  844. }
  845.  
  846. static void do_copper(void)
  847. {    
  848.     switch(copstate){
  849.      case COP_read:
  850.     copper_read();
  851.     break;
  852.      case COP_move:
  853.     if (copi1 >= (copcon & 2 ? 0x40 : 0x80))
  854.         custom_bank.wput(copi1,copi2);
  855.     copper_read();
  856.     break;
  857.      case COP_skip:
  858.     if (copcomp())
  859.         coplc += 4;
  860.     copper_read();
  861.     break;
  862.      case COP_wait: {        
  863.      int coptime = calc_copcomp_true(vpos, current_hpos());
  864.      if (coptime < 0) {
  865.          copstate = COP_stop;
  866.          eventtab[ev_copper].active = false;
  867.          copper_active = false;
  868.      } else {         
  869.          if (!coptime)
  870.               copper_read();
  871.          else {
  872.          eventtab[ev_copper].evtime = coptime;
  873.          eventtab[ev_copper].oldcycles = cycles;
  874.          }
  875.      }
  876.      break;
  877.      }
  878.      case COP_stop:
  879.     eventtab[ev_copper].active = false;
  880.     copper_active = false;
  881.     break;
  882.     }
  883. }
  884.  
  885. static __inline__ bool blitter_read(void)
  886. {
  887.     if (bltcon0 & 0xe00){
  888.     if (!dmaen(DMA_BLITTER)) return true; /* blitter stopped */
  889.     if (!blitline){
  890.         if (bltcon0 & 0x800) bltadat = chipmem_bank.wget(bltapt);
  891.         if (bltcon0 & 0x400) bltbdat = chipmem_bank.wget(bltbpt);
  892.     }
  893.     if (bltcon0 & 0x200) bltcdat = chipmem_bank.wget(bltcpt);
  894.     }
  895.     bltstate = BLT_work;
  896.     return (bltcon0 & 0xE00) != 0;
  897. }
  898.  
  899. static __inline__ bool blitter_write(void)
  900. {
  901.     if (bltddat) blitzero = false;
  902.     if ((bltcon0 & 0x100) || blitline){
  903.     if (!dmaen(DMA_BLITTER)) return true;
  904.     chipmem_bank.wput(bltdpt,bltddat);
  905.     }
  906.     bltstate = BLT_next;
  907.     return (bltcon0 & 0x100) != 0;
  908. }
  909.  
  910. static void blitter_blit(void)
  911. {
  912.     UWORD blitahold,blitbhold,blitchold;
  913.     UWORD bltaold;
  914.     
  915.     if (blitdesc) {
  916.     UWORD bltamask = 0xffff;
  917.     
  918.     if (!blitlpos) { bltamask &= bltafwm; }
  919.     if (blitlpos == (hblitsize - 1)) { bltamask &= bltalwm; }
  920.     bltaold = bltadat & bltamask;
  921.  
  922.     blitahold = (((ULONG)bltaold << 16) | blitpreva) >> (16-blitashift);
  923.     blitbhold = (((ULONG)bltbdat << 16) | blitprevb) >> (16-blitbshift);
  924.     blitchold = bltcdat;
  925.     } else {
  926.     UWORD bltamask = 0xffff;
  927.     
  928.     if (!blitlpos) { bltamask &= bltafwm; }
  929.     if (blitlpos == (hblitsize - 1)) { bltamask &= bltalwm; }
  930.     bltaold = bltadat & bltamask;
  931.  
  932.     blitahold = (((ULONG)blitpreva << 16) | bltaold) >> blitashift;
  933.     blitbhold = (((ULONG)blitprevb << 16) | bltbdat) >> blitbshift;
  934.     blitchold = bltcdat;
  935.     }
  936.     bltddat = 0;
  937.     bltddat = blit_func(blitahold, blitbhold, blitchold, bltcon0 & 0xFF);
  938.     if (blitfill){
  939.     UWORD fillmask;
  940.     for (fillmask = 1; fillmask; fillmask <<= 1){
  941.         UWORD tmp = bltddat;
  942.         if (blitfc) {
  943.         if (blitife)
  944.             bltddat |= fillmask;
  945.         else
  946.             bltddat ^= fillmask;
  947.         }
  948.         if (tmp & fillmask) blitfc = !blitfc;
  949.     }
  950.     }
  951.     bltstate = BLT_write;
  952.     blitpreva = bltaold; blitprevb = bltbdat;
  953. }
  954.  
  955. static void blitter_nxblit(void)
  956. {
  957.     bltstate = BLT_read;
  958.     if (blitdesc){
  959.     if (++blitlpos == hblitsize) {
  960.         if (--vblitsize == 0) {
  961.         bltstate = BLT_done;
  962. #ifdef NO_FAST_BLITTER
  963.         custom_bank.wput(0xDFF09C,0x8040);
  964. #endif
  965.         }
  966.         blitfc = bltcon1 & 0x4;
  967.  
  968.         blitlpos = 0;
  969.         if (bltcon0 & 0x800) bltapt -= 2+bltamod; 
  970.         if (bltcon0 & 0x400) bltbpt -= 2+bltbmod; 
  971.         if (bltcon0 & 0x200) bltcpt -= 2+bltcmod; 
  972.         if (bltcon0 & 0x100) bltdpt -= 2+bltdmod;
  973.     } else {
  974.         if (bltcon0 & 0x800) bltapt -= 2; 
  975.         if (bltcon0 & 0x400) bltbpt -= 2; 
  976.         if (bltcon0 & 0x200) bltcpt -= 2; 
  977.         if (bltcon0 & 0x100) bltdpt -= 2;        
  978.     }
  979.     } else {
  980.     if (++blitlpos == hblitsize) {
  981.         if (--vblitsize == 0) { 
  982.         bltstate = BLT_done;
  983. #ifdef NO_FAST_BLITTER
  984.         custom_bank.wput(0xDFF09C,0x8040);
  985. #endif
  986.         }
  987.         blitlpos = 0;
  988.         if (bltcon0 & 0x800) bltapt += 2+bltamod; 
  989.         if (bltcon0 & 0x400) bltbpt += 2+bltbmod; 
  990.         if (bltcon0 & 0x200) bltcpt += 2+bltcmod; 
  991.         if (bltcon0 & 0x100) bltdpt += 2+bltdmod;
  992.     } else {
  993.         if (bltcon0 & 0x800) bltapt += 2; 
  994.         if (bltcon0 & 0x400) bltbpt += 2; 
  995.         if (bltcon0 & 0x200) bltcpt += 2; 
  996.         if (bltcon0 & 0x100) bltdpt += 2;
  997.     }
  998.     }
  999. }
  1000.  
  1001. static __inline__ void blitter_line_incx(int a)
  1002. {
  1003.     blinea >>= 1;
  1004.     if (!blinea) {
  1005.     blinea = 0x8000;
  1006.     bltcnxlpt += 2;
  1007.     bltdnxlpt += 2;
  1008.     }
  1009. }
  1010.  
  1011. static __inline__ void blitter_line_decx(int shm)
  1012. {
  1013.     if (shm) blineb = (blineb << 2) | (blineb >> 14);
  1014.     blinea <<= 1;
  1015.     if (!blinea) {
  1016.     blinea = 1;
  1017.     bltcnxlpt -= 2;
  1018.     bltdnxlpt -= 2;
  1019.     }
  1020. }
  1021.  
  1022. static __inline__ void blitter_line_decy(int shm)
  1023. {
  1024.     if (shm) blineb = (blineb >> 1) | (blineb << 15);
  1025.     bltcnxlpt -= bltcmod;
  1026.     bltdnxlpt -= bltcmod; /* ??? am I wrong or doesn't KS1.3 set bltdmod? */
  1027.     blitonedot = 0;
  1028. }
  1029.  
  1030. static __inline__ void blitter_line_incy(int shm)
  1031. {
  1032.     if (shm) blineb = (blineb >> 1) | (blineb << 15);
  1033.     bltcnxlpt += bltcmod;
  1034.     bltdnxlpt += bltcmod; /* ??? */
  1035.     blitonedot = 0;
  1036. }
  1037.  
  1038. static void blitter_line(void)
  1039. {
  1040.     UWORD blitahold = blinea, blitbhold = blineb, blitchold = bltcdat;
  1041.     bltddat = 0;
  1042.     
  1043.     if (blitsing && blitonedot) blitahold = 0;
  1044.     blitonedot = 1;
  1045.     bltddat = blit_func(blitahold, blitbhold, blitchold, bltcon0 & 0xFF);
  1046.     if (!blitsign){
  1047.     bltapt += (WORD)bltamod;
  1048.     if (bltcon1 & 0x10){
  1049.         if (bltcon1 & 0x8)
  1050.             blitter_line_decy(0);
  1051.         else
  1052.             blitter_line_incy(0);
  1053.     } else {
  1054.         if (bltcon1 & 0x8)
  1055.             blitter_line_decx(0);
  1056.         else 
  1057.             blitter_line_incx(0);
  1058.     }
  1059.     } else {
  1060.     bltapt += (WORD)bltbmod;
  1061.     }
  1062.     if (bltcon1 & 0x10){
  1063.     if (bltcon1 & 0x4)
  1064.         blitter_line_decx(1);
  1065.     else
  1066.         blitter_line_incx(1);
  1067.     } else {
  1068.     if (bltcon1 & 0x4)
  1069.         blitter_line_decy(1);
  1070.     else
  1071.         blitter_line_incy(1);
  1072.     }
  1073.     blitsign = 0 > (WORD)bltapt;
  1074.     bltstate = BLT_write;
  1075. }
  1076.  
  1077. static __inline__ void blitter_nxline(void)
  1078. {
  1079.     if (--vblitsize == 0) {
  1080.     bltstate = BLT_done;
  1081. #ifdef NO_FAST_BLITTER
  1082.     custom_bank.wput(0xDFF09C,0x8040);
  1083. #endif
  1084.     } else {
  1085.     bltstate = BLT_read;
  1086.     bltcpt = bltcnxlpt;
  1087.     bltdpt = bltdnxlpt;
  1088.     }
  1089. }
  1090.  
  1091. static void blit_init(void)
  1092. {
  1093.     vblitsize = bltsize >> 6;
  1094.     hblitsize = bltsize & 0x3F;
  1095.     if (!vblitsize) vblitsize = 1024;
  1096.     if (!hblitsize) hblitsize = 64;
  1097.     blitlpos = 0;
  1098.     blitzero = true; blitpreva = blitprevb = 0;
  1099.     blitline = bltcon1 & 1;
  1100.     blitashift = bltcon0 >> 12; blitbshift = bltcon1 >> 12;
  1101.     
  1102.     if (blitline) {
  1103.     bltcnxlpt = bltcpt;
  1104.     bltdnxlpt = bltdpt;
  1105.     blitsing = bltcon1 & 0x2;
  1106.     blinea = bltadat >> blitashift;
  1107.     blineb = (bltbdat >> blitbshift) | (bltbdat << (16-blitbshift));
  1108.     blitsign = bltcon1 & 0x40; 
  1109.     blitonedot = false;
  1110.     bltamod &= 0xfffe; bltbmod &= 0xfffe; bltapt &= 0xfffe;
  1111.     } else {
  1112.     blitfc = bltcon1 & 0x4;
  1113.     blitife = bltcon1 & 0x8;
  1114.     blitfill = bltcon1 & 0x18;
  1115.  
  1116.     if ((bltcon1 & 0x18) == 0x18) {
  1117.         /* Digital "Trash" demo does this; others too. Apparently, no
  1118.          * negative effects. */
  1119.         static bool warn = true;
  1120.         if (warn)
  1121.             fprintf(stderr, "warning: weird fill mode (further messages suppressed)\n");
  1122.         warn = false;
  1123.     }
  1124.     blitdesc = bltcon1 & 0x2;
  1125.     if (blitfill && !blitdesc)
  1126.         fprintf(stderr, "warning: blitter fill without desc\n");
  1127.     }
  1128. }
  1129.  
  1130. #ifdef DEFERRED_INT
  1131.  
  1132. static UWORD deferred_bits;
  1133.  
  1134. static void defer_int_handler(void)
  1135. {
  1136.     INTREQ(0x8000 | deferred_bits);
  1137.     deferred_bits = 0;
  1138.     eventtab[ev_deferint].active = false;
  1139. }
  1140. #endif
  1141.  
  1142. void do_blitter(void)
  1143. {
  1144. #ifdef NO_FAST_BLITTER
  1145.     /* I'm not sure all this bltstate stuff is really necessary.
  1146.      * Most programs should be OK if the blit is done as soon as BLTSIZE is
  1147.      * written to, and the BLTFINISH bit is set some time after that.
  1148.      * This code here is nowhere near exact.
  1149.      */
  1150.     do {    
  1151.     switch(bltstate) {
  1152.      case BLT_init:
  1153.         blit_init();
  1154.         bltstate = BLT_read;
  1155.         /* fall through */
  1156.      case BLT_read:
  1157.         if (blitter_read())
  1158.             break;
  1159.         /* fall through */
  1160.      case BLT_work:
  1161.         if (blitline)
  1162.             blitter_line(); 
  1163.         else 
  1164.             blitter_blit();
  1165.         /* fall through */
  1166.      case BLT_write:
  1167.         if (blitter_write())
  1168.             break;
  1169.         /* fall through */
  1170.      case BLT_next:
  1171.         if (blitline)
  1172.             blitter_nxline();
  1173.         else 
  1174.             blitter_nxblit();
  1175.         break;
  1176.      case BLT_done:
  1177.         specialflags &= ~SPCFLAG_BLIT;
  1178.         break;
  1179.     }
  1180.     } while(bltstate != BLT_done && dmaen(DMA_BLITTER)
  1181.         && dmaen(DMA_BLITPRI));  /* blitter nasty -> no time for CPU */
  1182. #else
  1183.     if (bltstate == BLT_init) {
  1184.     blit_init();
  1185.     bltstate =  BLT_read;
  1186.     }
  1187.     if (!dmaen(DMA_BLITTER))
  1188.         return; /* gotta come back later. */
  1189.  
  1190.     if (blitline) {
  1191.     do {
  1192.         blitter_read();
  1193.         blitter_line();
  1194.         blitter_write();
  1195.         blitter_nxline();
  1196.     } while (bltstate != BLT_done);
  1197.     } else {
  1198.     do {    
  1199.         blitter_read();
  1200.         blitter_blit();
  1201.         blitter_write();
  1202.         blitter_nxblit();
  1203.     } while (bltstate != BLT_done);
  1204.     }
  1205.     eventtab[ev_deferint].active = true;
  1206.     eventtab[ev_deferint].oldcycles = cycles;
  1207.     eventtab[ev_deferint].evtime = 10; /* whatever */
  1208.     deferred_bits |= 0x40;
  1209.     events_schedule();
  1210.  
  1211.     specialflags &= ~SPCFLAG_BLIT;
  1212. #endif
  1213. }
  1214.  
  1215. void do_disk(void)
  1216. {
  1217. #ifdef NO_FAST_FLOPPY
  1218.     if (dskdmaen > 1 && dmaen(0x10)){
  1219.     if (--dsktime == 0) {
  1220.         dsktime = dskdelay;
  1221.         if (dsklen & 0x4000){
  1222.         UWORD dsksync_check;
  1223.         DISK_GetData(&dsksync_check, &dskbyte);
  1224.         dskbyte |= 0x8000;
  1225.         if (dsksynced || !(adkcon & 0x400)) {
  1226.             *mfmwrite++ = chipmem_bank.wget(dskpt); dskpt += 2;
  1227.             if (--dsklength == 0) {
  1228.             DISK_WriteData();
  1229.             custom_bank.wput(0xDFF09C, 0x8002); /*INTREQ->DSKBLK */
  1230.             dskdmaen = 0;
  1231.             specialflags &= ~SPCFLAG_DISK;
  1232.             }
  1233.         }
  1234.         if (dsksync_check == dsksync) {
  1235.             custom_bank.wput(0xDFF09C, 0x9000);
  1236.             dsksynced = true;
  1237.         }
  1238.         } else {
  1239.         DISK_GetData(&dskmfm, &dskbyte);
  1240.         dskbyte |= 0x8000;
  1241.         if (dsksynced || !(adkcon & 0x400)){
  1242.             chipmem_bank.wput(dskpt, dskmfm); dskpt += 2;
  1243.             if (--dsklength == 0) {
  1244.             custom_bank.wput(0xDFF09C, 0x8002);
  1245.             dskdmaen = 0;
  1246.             specialflags &= ~SPCFLAG_DISK;
  1247.             }
  1248.         }
  1249.         if (dskmfm == dsksync) {
  1250.             custom_bank.wput(0xDFF09C,0x9000);
  1251.             dsksynced = true;
  1252.         }
  1253.         }
  1254.     }
  1255.     }
  1256. #else
  1257.     if (dskdmaen > 1 && dmaen(0x10)){
  1258.     /* Just don't get into an infinite loop if the code below screws up */
  1259.     int ntries = 100000; 
  1260.     
  1261.     while (--ntries > 0 && (specialflags & SPCFLAG_DISK)) {
  1262.         if (dsklen & 0x4000){
  1263.         UWORD dsksync_check;
  1264.         DISK_GetData(&dsksync_check, &dskbyte);
  1265.         dskbyte |= 0x8000;
  1266.         if (dsksynced || !(adkcon & 0x400)) {
  1267.             *mfmwrite++ = chipmem_bank.wget(dskpt); dskpt += 2;
  1268.             if (--dsklength == 0) {
  1269.             DISK_WriteData();
  1270.             dskdmaen = 0;
  1271.             specialflags &= ~SPCFLAG_DISK;
  1272.             eventtab[ev_deferint].active = true;
  1273.             eventtab[ev_deferint].oldcycles = cycles;
  1274.             eventtab[ev_deferint].evtime = 10; /* whatever */
  1275.             events_schedule ();
  1276.             deferred_bits |= 0x0002;
  1277.             }
  1278.         }
  1279.         if (dsksync_check == dsksync) {
  1280.             /* This is pretty pointless... */
  1281.             custom_bank.wput(0xDFF09C, 0x9000);
  1282.             dsksynced = true;
  1283.         }
  1284.         } else {
  1285.         DISK_GetData(&dskmfm, &dskbyte);
  1286.         dskbyte |= 0x8000;
  1287.         if (dsksynced || !(adkcon & 0x400)){
  1288.             chipmem_bank.wput(dskpt, dskmfm); dskpt += 2;
  1289.             if (--dsklength == 0) {
  1290.             eventtab[ev_deferint].active = true;
  1291.             eventtab[ev_deferint].oldcycles = cycles;
  1292.             eventtab[ev_deferint].evtime = 10; /* whatever */
  1293.             events_schedule ();
  1294.             deferred_bits |= 0x0002;
  1295.             dskdmaen = 0;
  1296.             specialflags &= ~SPCFLAG_DISK;
  1297.             }
  1298.         }
  1299.         if (dskmfm == dsksync) {
  1300.             /* This is pretty pointless... */
  1301.             custom_bank.wput(0xDFF09C,0x9000);
  1302.             dsksynced = true;
  1303.         }
  1304.         }
  1305.     }
  1306.     }
  1307. #endif
  1308. }
  1309.  
  1310. static __inline__ void pfield_fetchdata(void)
  1311. {
  1312.     if (dmaen(0x100) && pfield_linedmaon) {
  1313.     switch(bplplanecnt){
  1314.      case 6:
  1315.         bpl6dat = chipmem_bank.wget(bpl6pt); bpl6pt += 2; bpl6dat <<= 5;
  1316.      case 5:
  1317.         bpl5dat = chipmem_bank.wget(bpl5pt); bpl5pt += 2; bpl5dat <<= 4;
  1318.      case 4:
  1319.         bpl4dat = chipmem_bank.wget(bpl4pt); bpl4pt += 2; bpl4dat <<= 3;
  1320.      case 3:
  1321.         bpl3dat = chipmem_bank.wget(bpl3pt); bpl3pt += 2; bpl3dat <<= 2;
  1322.      case 2:
  1323.         bpl2dat = chipmem_bank.wget(bpl2pt); bpl2pt += 2; bpl2dat <<= 1;
  1324.      case 1:
  1325.         bpl1dat = chipmem_bank.wget(bpl1pt); bpl1pt += 2;
  1326.     }
  1327.     }
  1328. }
  1329.  
  1330. static void pfield_hsync(int plfline)
  1331. {
  1332. }
  1333.  
  1334. static void do_sprites(int currvp)
  1335. {   
  1336.     int spr;
  1337.     for(spr = 0; spr < 8; spr++) {
  1338.     int vstart = (sprpos[spr] >> 8) | ((sprctl[spr] << 6) & 0x100);
  1339.     int vstop = (sprctl[spr] >> 8) | ((sprctl[spr] << 7) & 0x100);
  1340.     if ((vstart <= currvp && vstop >= currvp) || spron[spr] == 1) {
  1341.         if (dmaen(0x20)) {
  1342.         UWORD data1 = chipmem_bank.wget(sprpt[spr]);
  1343.         UWORD data2 = chipmem_bank.wget(sprpt[spr]+2);
  1344.         sprpt[spr] += 4;
  1345.         
  1346.         if (vstop != currvp && spron[spr] != 1) {
  1347.             SPRxDATB(data2, spr);
  1348.             SPRxDATA(data1, spr);
  1349.             if (!spr && !sprvbfl && ((sprpos[0]&0xff)<<2)>0x60) {
  1350.             sprvbfl=2; 
  1351.             spr0ctl=sprctl[0]; 
  1352.             spr0pos=sprpos[0]; 
  1353.             }
  1354.         } else {
  1355.             SPRxPOS(data1, spr);
  1356.             SPRxCTL(data2, spr);
  1357.         }
  1358.  
  1359. #if 0
  1360.         if (vstop != currvp && !sprptset[spr]) {
  1361.             SPRxDATB(data2, spr);
  1362.             SPRxDATA(data1, spr);
  1363.             if (!spr && !sprvbfl && ((sprpos[0]&0xff)<<2)>0x60) {
  1364.             sprvbfl=2; 
  1365.             spr0ctl=sprctl[0]; 
  1366.             spr0pos=sprpos[0]; 
  1367.             }
  1368.         } else {
  1369.             SPRxPOS(data1, spr);
  1370.             SPRxCTL(data2, spr);
  1371.             sprptset[spr] = false;
  1372.         }
  1373. #endif
  1374.         }
  1375.     }
  1376.     }
  1377. }
  1378.  
  1379. static void pfield_modulos(void)
  1380. {
  1381.     switch(bplplanecnt){
  1382.      case 6:
  1383.     bpl6pt += bpl2mod;
  1384.      case 5:
  1385.     bpl5pt += bpl1mod;
  1386.      case 4:
  1387.     bpl4pt += bpl2mod;
  1388.      case 3:
  1389.     bpl3pt += bpl1mod;
  1390.      case 2:
  1391.     bpl2pt += bpl2mod;
  1392.      case 1:
  1393.     bpl1pt += bpl1mod;
  1394.     }     
  1395. }
  1396.  
  1397. static void pfield_linetoscr(int pix, int stoppos)
  1398. {
  1399.     if (bplcon0 & 0x800 && bplplanecnt == 6) {
  1400.     /* HAM */
  1401.     static UWORD lastcolor;
  1402.     while (pix < diwfirstword && pix < stoppos) {
  1403.         DrawPixel((pix++)-16, acolors[0]);
  1404.         lastcolor = color_regs[0];
  1405.     }
  1406.     while (pix < diwlastword && pix < stoppos) {
  1407.         int pv = apixels[pix];
  1408.         switch(pv & 0x30) {
  1409.          case 0x00: lastcolor = color_regs[pv]; break;
  1410.          case 0x10: lastcolor &= 0xFF0; lastcolor |= (pv & 0xF); break;
  1411.          case 0x20: lastcolor &= 0x0FF; lastcolor |= (pv & 0xF) << 8; break;
  1412.          case 0x30: lastcolor &= 0xF0F; lastcolor |= (pv & 0xF) << 4; break;
  1413.         }
  1414.         
  1415.         if (spixstate[pix]) {
  1416.         DrawPixel(pix-16, acolors[spixels[pix]+16]);
  1417.         spixels[pix] = spixstate[pix] = 0;
  1418.         } else {
  1419.         DrawPixel(pix-16, xcolors[lastcolor]);
  1420.         }
  1421.         pix++;
  1422.     }
  1423.     while (pix < stoppos) {
  1424.         DrawPixel((pix++)-16, acolors[0]);
  1425.     }
  1426.     } else {        
  1427.     if (bplcon0 & 0x400) {
  1428.         int *lookup = (bplcon2 & 0x40) ? dblpf_ind2 : dblpf_ind1;
  1429.         /* Dual playfield */
  1430.         while (pix < diwfirstword && pix < stoppos) {
  1431.         DrawPixel((pix++)-16, acolors[0]);
  1432.         }
  1433.         while (pix < diwlastword && pix < stoppos) {
  1434.         if (spixstate[pix]) {
  1435.             DrawPixel(pix-16, acolors[spixels[pix]+16]);
  1436.             spixels[pix] = spixstate[pix] = 0;
  1437.         } else {
  1438.             DrawPixel(pix-16, acolors[lookup[apixels[pix]]]);
  1439.         }
  1440.         pix++;
  1441.         }
  1442.         while (pix < stoppos) {
  1443.         DrawPixel((pix++)-16, acolors[0]);
  1444.         }
  1445.     } else {    
  1446.         while (pix < diwfirstword && pix < stoppos) {
  1447.         DrawPixel((pix++)-16, acolors[0]);
  1448.         }
  1449.         while (pix < diwlastword && pix < stoppos) {
  1450.         if (spixstate[pix]) {
  1451.             if (apixels[pix] == 0 || spixstate[pix] < plf2pri)
  1452.             DrawPixel(pix-16, acolors[spixels[pix]+16]);
  1453.             else
  1454.             DrawPixel(pix-16, acolors[apixels[pix]]);
  1455.             spixels[pix] = spixstate[pix] = 0;
  1456.         } else {            
  1457.             DrawPixel(pix-16, acolors[apixels[pix]]);
  1458.         }
  1459.         pix++;
  1460.         }
  1461.         while (pix < stoppos) {
  1462.         DrawPixel((pix++)-16, acolors[0]);
  1463.         }
  1464.     }
  1465.     }
  1466. }
  1467.  
  1468. static void pfield_sprite (int num, int sprxp, UWORD data, UWORD datb)
  1469. {
  1470.     int i;
  1471.     for(i = 15; i >= 0; i--) {
  1472.     int sprxpos = sprxp + i*2;
  1473.     if ((sprctl[num] & 0x80) && (num & 1)) {
  1474.         /* Attached sprite */
  1475.         int col = ((data << 2) & 4) + ((datb << 3) & 8);
  1476.         if (col) {
  1477.         spixels[sprxpos] = col;
  1478.         spixels[sprxpos+1] = col;
  1479.         spixstate[sprxpos] = 1 << num;
  1480.         spixstate[sprxpos+1] = 1 << num;
  1481.         }
  1482.         spixstate[sprxpos] |= 1 << (num-1);
  1483.         spixstate[sprxpos+1] |= 1 << (num-1);
  1484.     } else {            
  1485.         int col = (data & 1) | ((datb << 1) & 2);
  1486.         if (spixstate[sprxpos] & (1 << num)) {
  1487.         /* finish attached sprite */
  1488.         /* Did the upper half of the sprite have any bits set? */
  1489.         if (spixstate[sprxpos] & (1 << (num+1)))
  1490.             col += spixels[sprxpos];
  1491.         if (!col) {
  1492.             spixstate[sprxpos] = spixstate[sprxpos+1] &= ~(3 << num);
  1493.         }
  1494.         } else {
  1495.         if (col) {
  1496.             col |= (num & 6) << 1;
  1497.         }
  1498.         }
  1499.         if (col) {
  1500.         spixels[sprxpos] = col;
  1501.         spixels[sprxpos+1] = col;
  1502.         spixstate[sprxpos] = 1<<num;
  1503.         spixstate[sprxpos+1] = 1<<num;
  1504.         }
  1505.     }
  1506.     data >>= 1;
  1507.     datb >>= 1;
  1508.     }   
  1509. }
  1510.  
  1511. void pfield_doline_slow(int currhpos)
  1512. {
  1513.     int xpos = currhpos * 4 - 0x60;
  1514.     static int nextpos = -1;
  1515.     static int linepos;
  1516.     static bool paststop = false;
  1517.     
  1518.     if (vpos < plffirstline || vpos >= plflastline) 
  1519.         return;
  1520.     
  1521.     if (currhpos == plfstrt) {    
  1522.     nextpos = currhpos;
  1523.     linepos = 0;
  1524.     paststop = false;
  1525.     }
  1526.     if (currhpos == nextpos) {    
  1527.     if (linepos >= plflinelen) {
  1528.         nextpos = -1;
  1529.         pfield_modulos();
  1530.     } else {        
  1531.         nextpos += bplhires ? 4 : 8;
  1532.         linepos += bplhires ? 4 : 8;
  1533.         
  1534.         pfield_fetchdata();
  1535.         
  1536.         if (bplhires) {
  1537.         int offs1 = 2 + xpos + 16 + bpldelay1*2; /* Never trust compilers, kids! */
  1538.         int offs2 = 2 + xpos + 16 + bpldelay2*2;
  1539.         
  1540.         int pix;
  1541.         for(pix = 15; pix >= 0; pix--) {
  1542.             switch(bplplanecnt) {
  1543.              case 4:
  1544.             apixels[pix + offs2] |= bpl4dat & 0x8; bpl4dat >>= 1;
  1545.              case 3:
  1546.             apixels[pix + offs1] |= bpl3dat & 0x4; bpl3dat >>= 1;
  1547.              case 2:
  1548.             apixels[pix + offs2] |= bpl2dat & 0x2; bpl2dat >>= 1;
  1549.              case 1:
  1550.             apixels[pix + offs1] |= bpl1dat & 0x1; bpl1dat >>= 1;
  1551.             }
  1552.         }
  1553.         } else {
  1554.         int offs1 = 2 + xpos + 32 + bpldelay1*2;
  1555.         int offs2 = 2 + xpos + 32 + bpldelay2*2;
  1556.         
  1557.         int pix;
  1558.         for(pix = 30; pix >= 0; pix -= 2) {
  1559.             switch(bplplanecnt) {
  1560.              case 6:
  1561.             apixels[pix + offs2] |= bpl6dat & 0x20;
  1562.             apixels[pix + offs2 + 1] |= bpl6dat & 0x20; bpl6dat >>= 1;
  1563.              case 5:
  1564.             apixels[pix + offs1] |= bpl5dat & 0x10;
  1565.             apixels[pix + offs1 + 1] |= bpl5dat & 0x10; bpl5dat >>= 1;
  1566.              case 4:
  1567.             apixels[pix + offs2] |= bpl4dat & 0x8;
  1568.             apixels[pix + offs2 + 1] |= bpl4dat & 0x8; bpl4dat >>= 1;
  1569.              case 3:
  1570.             apixels[pix + offs1] |= bpl3dat & 0x4; 
  1571.             apixels[pix + offs1 + 1] |= bpl3dat & 0x4; bpl3dat >>= 1;
  1572.              case 2:
  1573.             apixels[pix + offs2] |= bpl2dat & 0x2; 
  1574.             apixels[pix + offs2 + 1] |= bpl2dat & 0x2; bpl2dat >>= 1;
  1575.              case 1:
  1576.             apixels[pix + offs1] |= bpl1dat & 0x1; 
  1577.             apixels[pix + offs1 + 1] |= bpl1dat & 0x1; bpl1dat >>= 1;
  1578.             }
  1579.         }
  1580.         }    
  1581.     }
  1582.     }
  1583.     if (xpos > 0x60) { /* sprites can't appear that far to the left */
  1584.     int spr;
  1585.     for(spr = 7; spr >= 0; spr--) {
  1586.         if (sprarmed[spr] && xpos == ((sprpos[spr] & 0xFF) * 4) - 0x60) {
  1587.         int sprxp = xpos + 2 + (sprctl[spr] & 1)*2;
  1588.         pfield_sprite (spr, sprxp, sprdata[spr], sprdatb[spr]);
  1589.         }
  1590.     }
  1591.     }
  1592.     
  1593.     if (xpos >= 16 && xpos <= 812) {
  1594.     pfield_linetoscr (xpos, xpos+4);
  1595.     }
  1596. }
  1597.  
  1598. static __inline__ UWORD *pfield_xlateptr(CPTR plpt, int bytecount)
  1599. {
  1600.     if (!chipmem_bank.check(plpt,bytecount)) {
  1601.     fprintf(stderr, "Warning: Bad playfield pointer\n");
  1602.     return NULL;
  1603.     }
  1604.     return chipmem_bank.xlateaddr(plpt);
  1605. }
  1606.  
  1607. /*
  1608.  * A few hand-unrolled loops...
  1609.  */
  1610. static __inline__ void pfield_orword_hires(UWORD **plfptr, 
  1611.                        unsigned char **dataptr, int bit)
  1612. {
  1613.     UWORD data = *(*plfptr)++;
  1614.     unsigned char *pixptr = *dataptr;
  1615.     
  1616.     if (data & 0x8000) *pixptr |= bit;
  1617.     pixptr++;
  1618.     if (data & 0x4000) *pixptr |= bit;
  1619.     pixptr++;
  1620.     if (data & 0x2000) *pixptr |= bit;
  1621.     pixptr++;
  1622.     if (data & 0x1000) *pixptr |= bit;
  1623.     pixptr++;
  1624.     if (data & 0x800) *pixptr |= bit;
  1625.     pixptr++;
  1626.     if (data & 0x400) *pixptr |= bit;
  1627.     pixptr++;
  1628.     if (data & 0x200) *pixptr |= bit;
  1629.     pixptr++;
  1630.     if (data & 0x100) *pixptr |= bit;
  1631.     pixptr++;
  1632.     if (data & 0x80) *pixptr |= bit;
  1633.     pixptr++;
  1634.     if (data & 0x40) *pixptr |= bit;
  1635.     pixptr++;
  1636.     if (data & 0x20) *pixptr |= bit;
  1637.     pixptr++;
  1638.     if (data & 0x10) *pixptr |= bit;
  1639.     pixptr++;
  1640.     if (data & 0x8) *pixptr |= bit;
  1641.     pixptr++;
  1642.     if (data & 0x4) *pixptr |= bit;
  1643.     pixptr++;
  1644.     if (data & 0x2) *pixptr |= bit;
  1645.     pixptr++;
  1646.     if (data & 0x1) *pixptr |= bit;
  1647.     pixptr++;
  1648.     *dataptr = pixptr;
  1649. }
  1650.  
  1651. static __inline__ void pfield_orword_lores(UWORD **plfptr,
  1652.                        unsigned char **dataptr, int bit)
  1653. {
  1654.     UWORD data = *(*plfptr)++;
  1655.     unsigned char *pixptr = *dataptr;
  1656.     if (data & 0x8000) { *pixptr |= bit; *(pixptr+1) |= bit; }
  1657.     pixptr+=2;
  1658.     if (data & 0x4000) { *pixptr |= bit; *(pixptr+1) |= bit; }
  1659.     pixptr+=2;
  1660.     if (data & 0x2000) { *pixptr |= bit; *(pixptr+1) |= bit; }
  1661.     pixptr+=2;
  1662.     if (data & 0x1000) { *pixptr |= bit; *(pixptr+1) |= bit; }
  1663.     pixptr+=2;
  1664.     if (data & 0x800) { *pixptr |= bit; *(pixptr+1) |= bit; }
  1665.     pixptr+=2;
  1666.     if (data & 0x400) { *pixptr |= bit; *(pixptr+1) |= bit; }
  1667.     pixptr+=2;
  1668.     if (data & 0x200) { *pixptr |= bit; *(pixptr+1) |= bit; }
  1669.     pixptr+=2;
  1670.     if (data & 0x100) { *pixptr |= bit; *(pixptr+1) |= bit; }
  1671.     pixptr+=2;
  1672.     if (data & 0x80) { *pixptr |= bit; *(pixptr+1) |= bit; }
  1673.     pixptr+=2;
  1674.     if (data & 0x40) { *pixptr |= bit; *(pixptr+1) |= bit; }
  1675.     pixptr+=2;
  1676.     if (data & 0x20) { *pixptr |= bit; *(pixptr+1) |= bit; }
  1677.     pixptr+=2;
  1678.     if (data & 0x10) { *pixptr |= bit; *(pixptr+1) |= bit; }
  1679.     pixptr+=2;
  1680.     if (data & 0x8) { *pixptr |= bit; *(pixptr+1) |= bit; }
  1681.     pixptr+=2;
  1682.     if (data & 0x4) { *pixptr |= bit; *(pixptr+1) |= bit; }
  1683.     pixptr+=2;
  1684.     if (data & 0x2) { *pixptr |= bit; *(pixptr+1) |= bit; }
  1685.     pixptr+=2;
  1686.     if (data & 0x1) { *pixptr |= bit; *(pixptr+1) |= bit; }
  1687.     pixptr+=2;
  1688.     *dataptr = pixptr;
  1689. }
  1690.  
  1691. static __inline__ void pfield_setword_hires(UWORD **plfptr, 
  1692.                         unsigned char **dataptr, int bit)
  1693. {
  1694.     UWORD data = *(*plfptr)++;
  1695.     unsigned char *pixptr = *dataptr; 
  1696.     if (data & 0x8000) *pixptr++ = bit;
  1697.     else *pixptr++ = 0;
  1698.     if (data & 0x4000) *pixptr++ = bit;
  1699.     else *pixptr++ = 0;
  1700.     if (data & 0x2000) *pixptr++ = bit;
  1701.     else *pixptr++ = 0;
  1702.     if (data & 0x1000) *pixptr++ = bit;
  1703.     else *pixptr++ = 0;
  1704.     if (data & 0x800) *pixptr++ = bit;
  1705.     else *pixptr++ = 0;
  1706.     if (data & 0x400) *pixptr++ = bit;
  1707.     else *pixptr++ = 0;
  1708.     if (data & 0x200) *pixptr++ = bit;
  1709.     else *pixptr++ = 0;
  1710.     if (data & 0x100) *pixptr++ = bit;
  1711.     else *pixptr++ = 0;
  1712.     if (data & 0x80) *pixptr++ = bit;
  1713.     else *pixptr++ = 0;
  1714.     if (data & 0x40) *pixptr++ = bit;
  1715.     else *pixptr++ = 0;
  1716.     if (data & 0x20) *pixptr++ = bit;
  1717.     else *pixptr++ = 0;
  1718.     if (data & 0x10) *pixptr++ = bit;
  1719.     else *pixptr++ = 0;
  1720.     if (data & 0x8) *pixptr++ = bit;
  1721.     else *pixptr++ = 0;
  1722.     if (data & 0x4) *pixptr++ = bit;
  1723.     else *pixptr++ = 0;
  1724.     if (data & 0x2) *pixptr++ = bit;
  1725.     else *pixptr++ = 0;
  1726.     if (data & 0x1) *pixptr++ = bit;
  1727.     else *pixptr++ = 0;
  1728.     *dataptr = pixptr;
  1729. }
  1730.     
  1731. static __inline__ void pfield_setword_lores(UWORD **plfptr,
  1732.                         unsigned char **dataptr, int bit)
  1733. {
  1734.     UWORD data = *(*plfptr)++;
  1735.     unsigned char *pixptr = *dataptr;
  1736.     
  1737.     if (data & 0x8000) { *pixptr++ = bit; *pixptr++ = bit; }
  1738.     else { *pixptr++ = 0; *pixptr++ = 0; }
  1739.     if (data & 0x4000) { *pixptr++ = bit; *pixptr++ = bit; }
  1740.     else { *pixptr++ = 0; *pixptr++ = 0; }
  1741.     if (data & 0x2000) { *pixptr++ = bit; *pixptr++ = bit; }
  1742.     else { *pixptr++ = 0; *pixptr++ = 0; }
  1743.     if (data & 0x1000) { *pixptr++ = bit; *pixptr++ = bit; }
  1744.     else { *pixptr++ = 0; *pixptr++ = 0; }
  1745.     if (data & 0x800) { *pixptr++ = bit; *pixptr++ = bit; }
  1746.     else { *pixptr++ = 0; *pixptr++ = 0; }
  1747.     if (data & 0x400) { *pixptr++ = bit; *pixptr++ = bit; }
  1748.     else { *pixptr++ = 0; *pixptr++ = 0; }
  1749.     if (data & 0x200) { *pixptr++ = bit; *pixptr++ = bit; }
  1750.     else { *pixptr++ = 0; *pixptr++ = 0; }
  1751.     if (data & 0x100) { *pixptr++ = bit; *pixptr++ = bit; }
  1752.     else { *pixptr++ = 0; *pixptr++ = 0; }
  1753.     if (data & 0x80) { *pixptr++ = bit; *pixptr++ = bit; }
  1754.     else { *pixptr++ = 0; *pixptr++ = 0; }
  1755.     if (data & 0x40) { *pixptr++ = bit; *pixptr++ = bit; }
  1756.     else { *pixptr++ = 0; *pixptr++ = 0; }
  1757.     if (data & 0x20) { *pixptr++ = bit; *pixptr++ = bit; }
  1758.     else { *pixptr++ = 0; *pixptr++ = 0; }
  1759.     if (data & 0x10) { *pixptr++ = bit; *pixptr++ = bit; }
  1760.     else { *pixptr++ = 0; *pixptr++ = 0; }
  1761.     if (data & 0x8) { *pixptr++ = bit; *pixptr++ = bit; }
  1762.     else { *pixptr++ = 0; *pixptr++ = 0; }
  1763.     if (data & 0x4) { *pixptr++ = bit; *pixptr++ = bit; }
  1764.     else { *pixptr++ = 0; *pixptr++ = 0; }
  1765.     if (data & 0x2) { *pixptr++ = bit; *pixptr++ = bit; }
  1766.     else { *pixptr++ = 0; *pixptr++ = 0; }
  1767.     if (data & 0x1) { *pixptr++ = bit; *pixptr++ = bit; }
  1768.     else { *pixptr++ = 0; *pixptr++ = 0; }
  1769.     
  1770.     *dataptr = pixptr;
  1771. }
  1772.  
  1773. static void pfield_doline(void)
  1774. {
  1775.     int xpos = plfstrt * 4 - 0x60;
  1776.     int spr;
  1777.     int linelen;
  1778.  
  1779.     if (vpos < plffirstline || vpos >= plflastline) 
  1780.         return;
  1781.  
  1782.     if (dmaen(0x100) && pfield_linedmaon) {    
  1783.     /*
  1784.      * We want to use real pointers, but we don't want to get segfaults
  1785.          * because of them.
  1786.          */
  1787.     UWORD *r_bpl1pt,*r_bpl2pt,*r_bpl3pt,*r_bpl4pt,*r_bpl5pt,*r_bpl6pt;
  1788.     int bytecount = plflinelen / (bplhires ? 4 : 8) * 2;
  1789.     switch (bplplanecnt) {        
  1790.      case 6:
  1791.         r_bpl6pt = pfield_xlateptr(bpl6pt, bytecount);
  1792.         if (r_bpl6pt == NULL)
  1793.         return;
  1794.      case 5: 
  1795.         r_bpl5pt = pfield_xlateptr(bpl5pt, bytecount);
  1796.         if (r_bpl5pt == NULL)
  1797.         return;
  1798.      case 4:
  1799.         r_bpl4pt = pfield_xlateptr(bpl4pt, bytecount);
  1800.         if (r_bpl4pt == NULL)
  1801.         return;
  1802.      case 3:
  1803.         r_bpl3pt = pfield_xlateptr(bpl3pt, bytecount);
  1804.         if (r_bpl3pt == NULL)
  1805.         return;
  1806.      case 2: 
  1807.         r_bpl2pt = pfield_xlateptr(bpl2pt, bytecount);
  1808.         if (r_bpl2pt == NULL)
  1809.         return;
  1810.      case 1:
  1811.         r_bpl1pt = pfield_xlateptr(bpl1pt, bytecount);
  1812.         if (r_bpl1pt == NULL)
  1813.         return;
  1814.     } 
  1815.     switch (bplplanecnt) {        
  1816.      case 6: bpl6pt += bytecount + bpl2mod;
  1817.      case 5: bpl5pt += bytecount + bpl1mod;
  1818.      case 4: bpl4pt += bytecount + bpl2mod;
  1819.      case 3: bpl3pt += bytecount + bpl1mod;
  1820.      case 2: bpl2pt += bytecount + bpl2mod;
  1821.      case 1: bpl1pt += bytecount + bpl1mod;
  1822.     }
  1823.  
  1824.     if (bplhires) {    
  1825.         int xpos1 = 2 + xpos + 16 + bpldelay1*2;
  1826.         int xpos2 = 2 + xpos + 16 + bpldelay2*2;
  1827.         unsigned char *xp1ptr = apixels+xpos1;
  1828.         unsigned char *xp2ptr = apixels+xpos2;
  1829.  
  1830.         if (bplplanecnt > 0) {
  1831.         unsigned char *app = xp1ptr;
  1832.         for (linelen = plflinelen; linelen > 0; linelen-=4) {
  1833.             pfield_setword_hires(&r_bpl1pt, &app, 1);
  1834.         }
  1835.         if (bplplanecnt > 2) {
  1836.             unsigned char *app = xp1ptr;
  1837.             for (linelen = plflinelen; linelen > 0; linelen-=4) {
  1838.             pfield_orword_hires(&r_bpl3pt, &app, 4);
  1839.             }
  1840.         }
  1841.         if (bplplanecnt > 1) {
  1842.             unsigned char *app = xp2ptr;
  1843.             for (linelen = plflinelen; linelen > 0; linelen-=4) {
  1844.             pfield_orword_hires(&r_bpl2pt, &app, 2);
  1845.             }
  1846.         }
  1847.         if (bplplanecnt > 3) {
  1848.             unsigned char *app = xp2ptr;
  1849.             for (linelen = plflinelen; linelen > 0; linelen-=4) {
  1850.             pfield_orword_hires(&r_bpl4pt, &app, 8);
  1851.             }
  1852.         }
  1853.         } else {
  1854.         memset(apixels, 0, sizeof(apixels));
  1855.         }
  1856.     } else {
  1857.         int xpos1 = 2 + xpos + 32 + bpldelay1*2;
  1858.         int xpos2 = 2 + xpos + 32 + bpldelay2*2;
  1859.         unsigned char *xp1ptr = apixels+xpos1;
  1860.         unsigned char *xp2ptr = apixels+xpos2;
  1861.         if (bplplanecnt > 0) {
  1862.         unsigned char *app = xp1ptr;
  1863.         for (linelen = plflinelen; linelen > 0; linelen-=8) {
  1864.             pfield_setword_lores(&r_bpl1pt, &app, 1);
  1865.         }
  1866.         if (bplplanecnt > 2) {
  1867.             unsigned char *app = xp1ptr;
  1868.             for (linelen = plflinelen; linelen > 0; linelen-=8) {
  1869.             pfield_orword_lores(&r_bpl3pt, &app, 4);
  1870.             }
  1871.         }
  1872.         if (bplplanecnt > 4) {
  1873.             unsigned char *app = xp1ptr;
  1874.             for (linelen = plflinelen; linelen > 0; linelen-=8) {
  1875.             pfield_orword_lores(&r_bpl5pt, &app, 16);
  1876.             }
  1877.         }
  1878.         if (bplplanecnt > 1) {
  1879.             unsigned char *app = xp2ptr;
  1880.             for (linelen = plflinelen; linelen > 0; linelen-=8) {
  1881.             pfield_orword_lores(&r_bpl2pt, &app, 2);
  1882.             }
  1883.         }
  1884.         if (bplplanecnt > 3) {
  1885.             unsigned char *app = xp2ptr;
  1886.             for (linelen = plflinelen; linelen > 0; linelen-=8) {
  1887.             pfield_orword_lores(&r_bpl4pt, &app, 8);
  1888.             }
  1889.         }
  1890.         if (bplplanecnt > 5) {
  1891.             unsigned char *app = xp2ptr;
  1892.             for (linelen = plflinelen; linelen > 0; linelen-=8) {
  1893.             pfield_orword_lores(&r_bpl6pt, &app, 32);
  1894.             }
  1895.         }
  1896.         } else {
  1897.         memset(apixels, 0, sizeof(apixels));
  1898.         }
  1899.     }
  1900.     }
  1901.     for(spr = 7; spr >= 0; spr--) {
  1902.     if (sprarmed[spr]) {
  1903.         int sprxp = ((sprpos[spr] & 0xFF) * 4) - 0x60 + 2 + (sprctl[spr] & 1)*2;
  1904.         int i;
  1905.         /* Ugh. Nasty bug. Let's rather lose some sprites than trash
  1906.          * memory. */
  1907.         if (sprxp < 0)
  1908.         continue;
  1909.         pfield_sprite (spr, sprxp, sprdata[spr], sprdatb[spr]);
  1910.     }
  1911.     }
  1912.     
  1913.     pfield_linetoscr (16, 812);
  1914. }
  1915.  
  1916. static void setdontcare(void)
  1917. {
  1918.     printf("Don't care mouse mode set\n");
  1919.     mousestate=dont_care_mouse;
  1920.     lastspr0x=lastmx; lastspr0y=lastmy;
  1921.     mstepx=defstepx; mstepy=defstepy;
  1922. }
  1923.  
  1924. static void setfollow(void)
  1925. {
  1926.     printf("Follow sprite mode set\n");
  1927.     mousestate=follow_mouse;
  1928.     lastdiffx=lastdiffy=0;
  1929.     sprvbfl=0;
  1930.     spr0ctl=spr0pos=0;
  1931.     mstepx=defstepx; mstepy=defstepy;
  1932. }
  1933.  
  1934. void togglemouse(void)
  1935. {
  1936.     switch(mousestate) {
  1937.      case dont_care_mouse: setfollow(); break;
  1938.      case follow_mouse: setdontcare(); break;
  1939.     }
  1940. }        
  1941.  
  1942. #if 0 /* Mouse calibrations works well enough without this. */
  1943. void mousesetup(void)
  1944. {
  1945.     if (mousestate != follow_mouse) return;
  1946.     char buf[80];
  1947.     printf("\nMouse pointer centering.\n\n");
  1948.     printf("Current values: xoffs=0x%x yoffs=0x%x\n", xoffs, yoffs);
  1949.     printf("New values (y/n)?";
  1950.     cin.get(buf,80,'\n');
  1951.     if (toupper(buf[0]) != 'Y') return;
  1952.     cout << "\nxoffs= "; cin>>xoffs;
  1953.     cout << "yoffs= "; cin>>yoffs;
  1954.     cout << "\n";
  1955. }
  1956. #endif
  1957.  
  1958. static __inline__ int adjust(int val)
  1959. {
  1960.     if (val>127)
  1961.     return 127; 
  1962.     else if (val<-127)
  1963.     return -127;
  1964.     return val;
  1965. }
  1966.  
  1967. static void vsync_handler(void)
  1968. {
  1969.     int spr0x = ((spr0pos & 0xff) << 2) | ((spr0ctl & 1) << 1);
  1970.     int spr0y = ((spr0pos >> 8) | ((spr0ctl & 4) << 6)) << 1;
  1971.     int diffx, diffy;
  1972.     int i;
  1973.     
  1974.     handle_events();
  1975. #ifdef HAVE_JOYSTICK
  1976.     {
  1977.     UWORD dir;
  1978.     bool button;
  1979.     read_joystick(&dir, &button);
  1980.     buttonstate[1] = button;
  1981.     }
  1982. #endif
  1983.  
  1984.     if (produce_sound)
  1985.     flush_sound ();
  1986.     
  1987.     switch (mousestate) {
  1988.      case normal_mouse:
  1989.     diffx = lastmx - lastsampledmx;
  1990.     diffy = lastmy - lastsampledmy;
  1991.     if (!newmousecounters) {    
  1992.         if (diffx > 127) diffx = 127;
  1993.         if (diffx < -127) diffx = -127;
  1994.         joy0x += diffx;
  1995.         if (diffy > 127) diffy = 127;
  1996.         if (diffy < -127) diffy = -127;
  1997.         joy0y += diffy;
  1998.     }
  1999.     lastsampledmx += diffx; lastsampledmy += diffy;
  2000.     break;
  2001.  
  2002.      case dont_care_mouse:
  2003.     diffx = adjust (((lastmx-lastspr0x) * mstepx) >> 16);
  2004.     diffy = adjust (((lastmy-lastspr0y) * mstepy) >> 16);
  2005.     lastspr0x=lastmx; lastspr0y=lastmy;
  2006.     joy0x+=diffx; joy0y+=diffy;
  2007.     break;
  2008.     
  2009.      case follow_mouse:
  2010.     if (sprvbfl && sprvbfl-- >1) {
  2011.         int mouseypos;
  2012.         
  2013.         if ((lastdiffx > docal || lastdiffx < -docal) && lastspr0x != spr0x 
  2014.         && spr0x > plfstrt*4+34+xcaloff && spr0x < plfstop*4-xcaloff)
  2015.         {  
  2016.         int val = (lastdiffx << 16) / (spr0x - lastspr0x);
  2017.         if (val>=0x8000) mstepx=(mstepx*(calweight-1)+val)/calweight;
  2018.         }
  2019.         if ((lastdiffy > docal || lastdiffy < -docal) && lastspr0y != spr0y
  2020.         && spr0y>plffirstline+ycaloff && spr0y<plflastline-ycaloff) 
  2021.         { 
  2022.         int val = (lastdiffy<<16) / (spr0y-lastspr0y);
  2023.         if (val>=0x8000) mstepy=(mstepy*(calweight-1)+val)/calweight;
  2024.         }
  2025.         mouseypos = lastmy;
  2026.  
  2027.         /* Calculations might be incorrect */
  2028.         if(dont_want_aspect)
  2029.             mouseypos *= 2;
  2030.  
  2031.         /* cout<<" mstepx= "<<mstepx<<" mstepy= "<<mstepy<<"\n";*/
  2032.         diffx = adjust ((((lastmx + 0x70 + xoffs - spr0x) & ~1) * mstepx) >> 16);
  2033.         diffy = adjust ((((mouseypos + yoffs - spr0y+minfirstline*2) & ~1) * mstepy) >> 16);
  2034.         lastspr0x=spr0x; lastspr0y=spr0y;
  2035.         lastdiffx=diffx; lastdiffy=diffy;
  2036.         joy0x+=diffx; joy0y+=diffy; 
  2037.     }
  2038.     break;
  2039.     }
  2040.  
  2041.     INTREQ(0x8020);
  2042.     if (bplcon0 & 4) lof ^= 0x8000;
  2043.     COPJMP1(0);
  2044.     
  2045.     for (i = 0; i < 8; i++)
  2046.     spron[i] = 0;
  2047.  
  2048.     if (framecnt == 0)
  2049.         flush_screen ();
  2050.     count_frame();    
  2051. #ifdef __unix
  2052.     {
  2053.     struct timeval tv;
  2054.     unsigned long int newtime;
  2055.     
  2056.     gettimeofday(&tv,NULL);    
  2057.     newtime = (tv.tv_sec-seconds_base) * 1000 + tv.tv_usec / 1000;
  2058.     
  2059.     if (!bogusframe) {    
  2060.         frametime += newtime - msecs;
  2061.         timeframes++;
  2062.     }
  2063.     msecs = newtime;
  2064.     bogusframe = false;
  2065.     }
  2066. #endif
  2067.     CIA_vsync_handler();
  2068. }
  2069.  
  2070. static void hsync_handler(void)
  2071. {
  2072.     eventtab[ev_hsync].oldcycles = cycles;
  2073.     CIA_hsync_handler();
  2074.     
  2075.     if(produce_sound)
  2076.     do_sound ();
  2077.  
  2078.     if (framecnt == 0 && vpos >= plffirstline && vpos < plflastline 
  2079.     && vpos >= minfirstline) 
  2080.     {
  2081.     /* Finish the line, if we started doing it with the slow update.
  2082.      * Otherwise, draw it entirely. */
  2083.     if (pfield_fullline) {        
  2084.         if (!pfield_linedone) {        
  2085.             pfield_doline();
  2086.         }
  2087.     } else {
  2088.         int i;
  2089.         for(i = pfield_lastpart_hpos; i < maxhpos; i++)
  2090.             pfield_doline_slow(i);
  2091.     }
  2092.     flush_line ();
  2093.     }
  2094.     pfield_calclinedma();
  2095.     pfield_fullline = true;
  2096.     pfield_linedone = false;
  2097.     pfield_lastpart_hpos = 0;
  2098.  
  2099.     if (++vpos == (maxvpos + (lof != 0))) {
  2100.     vpos = 0;
  2101.     vsync_handler();
  2102.     }
  2103.     
  2104.     /* Tell the graphics code about the next line. */
  2105.     if (framecnt == 0 && vpos >= plffirstline && vpos < plflastline
  2106.     && vpos >= minfirstline) 
  2107.     {
  2108.     if (dont_want_aspect) {
  2109.         prepare_line(vpos - minfirstline, false);
  2110.     } else {
  2111.         if (bplcon0 & 4) {
  2112.         if(lof) {
  2113.             prepare_line((vpos-minfirstline)*2, false);
  2114.         } else {
  2115.             prepare_line((vpos-minfirstline)*2+1, false);
  2116.         }
  2117.         } else {
  2118.         prepare_line((vpos-minfirstline)*2, true);
  2119.         }
  2120.     }
  2121.     }
  2122.  
  2123.     /* do_sprites must be called after pfield_lastpart_hpos
  2124.      * is set to 0. */
  2125.     if (vpos > 0) do_sprites(vpos);
  2126. }
  2127.  
  2128. void customreset(void)
  2129. {
  2130.     int i;
  2131. #ifdef __unix
  2132.     struct timeval tv;
  2133. #endif
  2134.     inhibit_frame = 0;
  2135.     CIA_reset();
  2136.     cycles = 0; specialflags = 0;
  2137.     
  2138.     vpos = 0; lof = 0;
  2139.     
  2140.     if (needmousehack()) {
  2141.         if (mousestate != follow_mouse) setfollow();
  2142.     } else {
  2143.     mousestate = normal_mouse;
  2144.     }
  2145.  
  2146.     memset(spixels, 0, sizeof(spixels));
  2147.     memset(spixstate, 0, sizeof(spixstate));
  2148.     
  2149.     prepare_line(0, false); /* Get the graphics stuff in a sane state */
  2150.     
  2151.     dmacon = intena = 0;
  2152.     bltstate = BLT_done;
  2153.     copstate = COP_stop;
  2154.     copcon = 0;
  2155.     dskdmaen = 0;
  2156.     cycles = 0;
  2157.     for(i = ev_copper; i < ev_max; i++) {
  2158.     eventtab[i].active = false;
  2159.     eventtab[i].oldcycles = 0;
  2160.     }
  2161.     copper_active = false;
  2162.     eventtab[ev_cia].handler = CIA_handler;
  2163.     eventtab[ev_copper].handler = do_copper;
  2164.     eventtab[ev_hsync].handler = hsync_handler;
  2165.     eventtab[ev_hsync].evtime = maxhpos;
  2166.     eventtab[ev_hsync].active = true;
  2167. #ifdef DEFERRED_INT
  2168.     eventtab[ev_deferint].handler = defer_int_handler;
  2169.     eventtab[ev_deferint].active = false;
  2170.     deferred_bits = 0;
  2171. #endif
  2172.     events_schedule();
  2173.     
  2174. #ifdef __unix
  2175.     gettimeofday(&tv,NULL);
  2176.     seconds_base = tv.tv_sec;
  2177.     bogusframe = true;
  2178. #endif
  2179. }
  2180.  
  2181. void dumpcustom(void)
  2182. {
  2183.  
  2184.     printf("DMACON: %x INTENA: %x INTREQ: %x VPOS: %x HPOS: %x\n", DMACONR(),
  2185.        intena, intreq, vpos, current_hpos());
  2186.     if (timeframes) { 
  2187.     printf("Average frame time: %d ms [frames: %d time: %d]\n", 
  2188.            frametime/timeframes, timeframes, frametime);
  2189.     }
  2190. }
  2191.  
  2192. int intlev(void)
  2193. {
  2194.     UWORD imask = intreq & intena;
  2195.     if (imask && (intena & 0x4000)){
  2196.     if (imask & 0x2000) return 6;
  2197.     if (imask & 0x1800) return 5;
  2198.     if (imask & 0x0780) return 4;
  2199.     if (imask & 0x0070) return 3;
  2200.     if (imask & 0x0008) return 2;
  2201.     if (imask & 0x0007) return 1;
  2202.     }
  2203.     return -1;
  2204. }
  2205.  
  2206. void custom_init(void)
  2207. {
  2208.     int num;
  2209.     setfollow();
  2210.     customreset();
  2211.     for (num = 0; num < 64; num++) {    
  2212.     int plane1 = (num & 1) | ((num >> 1) & 2) | ((num >> 2) & 4);
  2213.     int plane2 = ((num >> 1) & 1) | ((num >> 2) & 2) | ((num >> 3) & 4);
  2214.     if (plane2 > 0) plane2 += 8;
  2215.     dblpf_ind1[num] = plane1 == 0 ? plane2 : plane1;
  2216.     dblpf_ind2[num] = plane2 == 0 ? plane1 : plane2;
  2217.     }
  2218. }
  2219.